package com.mrzhou.web.config;

import com.mrzhou.core.tool.utils.JacksonUtil;
import com.mrzhou.web.handler.HttpErrorHandler;
import com.mrzhou.web.props.HttpClientPoolProperties;
import com.mrzhou.web.support.HttpClientConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.*;

@Configuration
@ConditionalOnClass(value = {RestTemplate.class, CloseableHttpClient.class})
@Slf4j
public class RestTemplateConfiguration {

    @Autowired
    private HttpClientPoolProperties httpClientPoolProperties;

    /**
     * 初始化RestTemplate,并加入spring的Bean工厂，由spring统一管理
     */
    @Bean
    public RestTemplate restTemplate(@Qualifier("clientHttpRequestFactory") ClientHttpRequestFactory factory) {
        return createRestTemplate(factory);
    }

    /**
     * 创建Http客户端工厂
     */
    @Bean(name = "clientHttpRequestFactory")
    public ClientHttpRequestFactory clientHttpRequestFactory() throws Exception {
        log.info("HttpClient读取到的配置信息: {}", JacksonUtil.toJsonString(httpClientPoolProperties));
        // 配置的maxTotalConnect和maxPreRoute要为正常的
        if (httpClientPoolProperties.getMaxTotalConnect() <= 0) {
            throw new IllegalArgumentException("invalid maxTotalConnection: " + httpClientPoolProperties.getMaxTotalConnect());
        }
        if (httpClientPoolProperties.getMaxPreRoute() <= 0) {
            throw new IllegalArgumentException("invalid maxConnectionPerRoute: " + httpClientPoolProperties.getMaxPreRoute());
        }
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(HttpClientConfig.createHttpClient(httpClientPoolProperties));
        // 设置连接超时时间
        clientHttpRequestFactory.setConnectTimeout(httpClientPoolProperties.getConnectTimeout());
        // 读超时时间
        clientHttpRequestFactory.setReadTimeout(httpClientPoolProperties.getReadTimeout());
        // 从连接池中获取请求的超时时间, 不宜过长; 必须设置! 比如连接不够用时,时间过长将时灾难性的
        clientHttpRequestFactory.setConnectionRequestTimeout(httpClientPoolProperties.getConnectionRequestTimeout());
        return clientHttpRequestFactory;
    }

    private RestTemplate createRestTemplate(ClientHttpRequestFactory factory) {
        RestTemplate restTemplate = new RestTemplate(factory);

        //我们采用RestTemplate内部的MessageConverter
        //重新设置StringHttpMessageConverter字符集，解决中文乱码问题
        modifyDefaultCharset(restTemplate);

        restTemplate.setErrorHandler(new HttpErrorHandler()); // 自定义处理HttpClient请求返回的异常

        return restTemplate;
    }

    /**
     * 修改默认的字符集类型为utf-8
     *
     * @param restTemplate
     */
    private void modifyDefaultCharset(RestTemplate restTemplate) {
        List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
        HttpMessageConverter<?> converterTarget = null;
        for (HttpMessageConverter<?> item : converterList) {
            if (StringHttpMessageConverter.class == item.getClass()) {
                converterTarget = item;
                break;
            }
        }
        if (null != converterTarget) {
            converterList.remove(converterTarget);
        }
        Charset defaultCharset = Charset.forName(httpClientPoolProperties.getCharset());
        converterList.add(1, new StringHttpMessageConverter(defaultCharset));
    }

}
